package pers.chy.chyappointmentplatform.Controller;

import com.google.gson.Gson;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import pers.chy.chyappointmentplatform.Model.NoMapping.ReplyMsgDTO;
import pers.chy.chyappointmentplatform.Model.NoMapping.UserDTO;
import pers.chy.chyappointmentplatform.Model.NoMapping.WorkingTimeYsDTO;
import pers.chy.chyappointmentplatform.Model.NoMapping.YjztDTO;
import pers.chy.chyappointmentplatform.Model.T_LydjExtDTO;
import pers.chy.chyappointmentplatform.Model.V_SqdDetailExtDTO;
import pers.chy.chyappointmentplatform.Model.Yjyy_PdjhDTO;
import pers.chy.chyappointmentplatform.Service.SmsService;
import pers.chy.chyappointmentplatform.Service.StatisticService;
import pers.chy.chyappointmentplatform.Utils.ChyException;
import pers.chy.chyappointmentplatform.Utils.ExcelData;
import pers.chy.chyappointmentplatform.Utils.ExcelUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@CrossOrigin        // 允许跨域请求
@RequestMapping("StatisticController")
public class StatisticController {

    @Autowired
    private StatisticService statisticService;

    @Autowired
    private SmsService smsService;

    /**
     * 申请单明细统计
     *
     * @param params
     * @param request
     * @return
     */
    @RequestMapping("getSqdDetail")
    public String getSqdDetail(@RequestBody Map params, HttpServletRequest request) {
        ReplyMsgDTO replyMsgDTO = new ReplyMsgDTO();

        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class); // 使用指定的类XXX初始化日志对象，方便在日志输出的时候，可以打印出日志信息所属的类。
        log.info("[Controller入参]：" + params);

        // 报表1
        String method = (String) params.get("method");

        if ("US".equals(method)) {
            try {
                List<V_SqdDetailExtDTO> res = statisticService.doGetSqdDetail_US(params);
                // 业务成功
                replyMsgDTO.setStatus(true);
                replyMsgDTO.setDetail(new Gson().toJson(res));
            } catch (Exception ex) {
                // 业务失败
                replyMsgDTO.setStatus(false);
                replyMsgDTO.setDetail(ex.getMessage());
                // 异常日志
                if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
                else log.error("[不期望的异常]", ex);
            }

        } else {
            try {
                // 获取这个日期下的所有申请单
                List<V_SqdDetailExtDTO> sqdDetailDTOList = statisticService.doGetSqdDetail_bb1(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */

                //
                // 分类：按报告医生分类
                //
                Map<String, List<V_SqdDetailExtDTO>> groupByBgys = new HashMap<>();
                for (V_SqdDetailExtDTO sqd : sqdDetailDTOList) {
                    String bgys = sqd.getBgys();
                    if (bgys != null) {
                        // 取这个报告医生的申请单列表
                        List<V_SqdDetailExtDTO> sqdListOfBgys = groupByBgys.get(bgys);
                        if (sqdListOfBgys == null) {
                            groupByBgys.put(bgys, new ArrayList<>());    // 不存在则新建
                            sqdListOfBgys = groupByBgys.get(bgys);      // 新建后写入申请单
                            sqdListOfBgys.add(sqd);
                        } else {
                            sqdListOfBgys.add(sqd); // 存在此医生分类，则直接追加
                        }
                    }
                    //                else{log.error("发现申请单{}的报告医生为空！跳过，不写入报表",sqd.getSqdh());}
                }

                //
                // 排序：每个医生的所有病人按报告时间排序
                //
                for (Map.Entry<String, List<V_SqdDetailExtDTO>> entry1 : groupByBgys.entrySet()) {
                    List<V_SqdDetailExtDTO> mapValue = entry1.getValue();
                    for (int i = 0; i < mapValue.size() - 1; i++) {
                        for (int j = 0; j < mapValue.size() - 1 - i; j++) {
                            if (mapValue.get(j).getBgsj().after(mapValue.get(j + 1).getBgsj())) { // 从早到晚
                                V_SqdDetailExtDTO temp = mapValue.get(j);
                                mapValue.set(j, mapValue.get(j + 1));
                                mapValue.set(j + 1, temp);
                            }
                        }
                    }
                }

                //
                // 排序：申请单多的医生排在前面
                //
                List<String> keyList = new ArrayList<>();
                List<Integer> sizeList = new ArrayList<>();
                for (Map.Entry<String, List<V_SqdDetailExtDTO>> entry : groupByBgys.entrySet()) {
                    String mapKey = entry.getKey();
                    List<V_SqdDetailExtDTO> mapValue = entry.getValue();
                    keyList.add(mapKey);
                    sizeList.add(mapValue.size());
                }
                // 因为HashMap不能重新排序（顺序取决于HashCode），所以只能单独建一个List存放顺序（每个医生申请单数量由高到低的顺序）
                for (int i = 0; i < sizeList.size(); i++) { // 冒泡排序
                    for (int j = 0; j < sizeList.size() - 1 - i; j++) {
                        if (sizeList.get(j) < sizeList.get(j + 1)) {
                            // 交换
                            Integer temp1 = sizeList.get(j);
                            sizeList.set(j, sizeList.get(j + 1));
                            sizeList.set(j + 1, temp1);
                            // 交换
                            String temp2 = keyList.get(j);
                            keyList.set(j, keyList.get(j + 1));
                            keyList.set(j + 1, temp2);
                        }
                    }
                }

                // 业务成功
                replyMsgDTO.setStatus(true);
                replyMsgDTO.setDetail(new Gson().toJson(groupByBgys));
                replyMsgDTO.setAdditional1(new Gson().toJson(keyList));

            } catch (Exception ex) {
                // 业务失败
                replyMsgDTO.setStatus(false);
                replyMsgDTO.setDetail(ex.getMessage());
                // 异常日志
                if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
                else log.error("[不期望的异常]", ex);
            }
        }

        //
        String replyMsgStr = new Gson().toJson(replyMsgDTO);
        if (replyMsgDTO.isStatus() == true) {
            log.info("[Controller出参]：报表内容（略）");
        } else {
            log.info("[Controller出参]：" + replyMsgStr);
        }

        return replyMsgStr;
    }

    /**
     * 医生的工作时长统计
     *
     * @param params
     * @param request
     * @return
     */
    @RequestMapping("getWorkingTime_Ys")
    public String getWorkingTime_Ys(@RequestBody Map params, HttpServletRequest request) {
        ReplyMsgDTO replyMsgDTO = new ReplyMsgDTO();

        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class); // 使用指定的类XXX初始化日志对象，方便在日志输出的时候，可以打印出日志信息所属的类。
        log.info("[Controller入参]：" + params);

        try {
            // 获取工作日期下的工作时长
            List<WorkingTimeYsDTO> res = statisticService.doGetWorkingHors_Ys(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            replyMsgDTO.setStatus(true);
            replyMsgDTO.setDetail(new Gson().toJson(res));
        } catch (Exception ex) {
            // 业务失败
            replyMsgDTO.setStatus(false);
            replyMsgDTO.setDetail(ex.getMessage());
            // 异常日志
            if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
            else log.error("[不期望的异常]", ex);
        }

        //
        String replyMsgStr = new Gson().toJson(replyMsgDTO);
        if (replyMsgDTO.isStatus() == true) {
            log.info("[Controller出参]：报表内容（略）");
        } else {
            log.info("[Controller出参]：" + replyMsgStr);
        }

        return replyMsgStr;
    }


    /**
     * 统计医技组套列表
     *
     * @param params
     * @param request
     * @return
     */
    @RequestMapping("getYjzt")
    public String getYjzt(@RequestBody Map params, HttpServletRequest request) {
        ReplyMsgDTO replyMsgDTO = new ReplyMsgDTO();

        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class); // 使用指定的类XXX初始化日志对象，方便在日志输出的时候，可以打印出日志信息所属的类。
        log.info("[Controller入参]：" + params);

        try {
            // 获取医技组套数据
            List<YjztDTO> res = statisticService.doGetYjzt(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            replyMsgDTO.setStatus(true);
            replyMsgDTO.setDetail(new Gson().toJson(res));
        } catch (Exception ex) {
            // 业务失败
            replyMsgDTO.setStatus(false);
            replyMsgDTO.setDetail(ex.getMessage());
            // 异常日志
            if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
            else log.error("[不期望的异常]", ex);
        }

        //
        String replyMsgStr = new Gson().toJson(replyMsgDTO);
        if (replyMsgDTO.isStatus() == true) {
            log.info("[Controller出参]：报表内容（略）");
        } else {
            log.info("[Controller出参]：" + replyMsgStr);
        }

        return replyMsgStr;
    }


    /**
     * 统计组套的工作时长
     *
     * @param params
     * @param request
     * @return
     */
    @RequestMapping("getWorkingTime_Zt")
    public String getWorkingTime_Zt(@RequestBody Map params, HttpServletRequest request) {
        ReplyMsgDTO replyMsgDTO = new ReplyMsgDTO();

        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class); // 使用指定的类XXX初始化日志对象，方便在日志输出的时候，可以打印出日志信息所属的类。
        log.info("[Controller入参]：" + params);

        try {
            // 获取工作日期下的工作时长
            List<YjztDTO> res = statisticService.doGetWorkingHors_Zt(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            replyMsgDTO.setStatus(true);
            replyMsgDTO.setDetail(new Gson().toJson(res));
        } catch (Exception ex) {
            // 业务失败
            replyMsgDTO.setStatus(false);
            replyMsgDTO.setDetail(ex.getMessage());
            // 异常日志
            if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
            else log.error("[不期望的异常]", ex);
        }

        //
        String replyMsgStr = new Gson().toJson(replyMsgDTO);
        if (replyMsgDTO.isStatus() == true) {
            log.info("[Controller出参]：报表内容（略）");
        } else {
            log.info("[Controller出参]：" + replyMsgStr);
        }

        return replyMsgStr;
    }


    /**
     * 导出excle（测试）
     *
     * @param params
     * @param response
     * @return
     */
    @RequestMapping(value = "/exportExcle_TEST")
    public String exportExcle_TEST(@RequestBody Map params, HttpServletResponse response) {
        try {
            // 组成exlce的Bean对象集合
            List<Student> studentList = new ArrayList<>();
            Student temp = new Student();
            temp.name = "陈呵呵";
            temp.age = 26;
            studentList.add(temp);

            // Bean对象的值转为String数组
            if (!CollectionUtils.isEmpty(studentList)) {
                //excel列头信息
                String[] heads = {"姓名", "年龄"};
                List<String[]> dataList = new ArrayList<String[]>();
                String[] objs = null;
                for (int i = 0; i < studentList.size(); i++) {
                    Student stu = studentList.get(i);
                    objs = new String[heads.length];
                    objs[0] = String.valueOf(stu.name);
                    objs[1] = String.valueOf(stu.age);
                    dataList.add(objs);
                }
                ExcelData excelData = new ExcelData();
                excelData.setFileName(UUID.randomUUID().toString() + ".xls");
                excelData.setHead(heads);
                excelData.setData(dataList);
                ExcelUtil.exportExcel(response, excelData);
                return "success";
            }
        } catch (Exception ex) {
        }
        return "fail";
    }


    /**
     * 导出excel（疫苗叫号）
     *
     * @return
     */
    @RequestMapping(value = "/exportExcle_YM")
    public String exportExcle_YM(@RequestBody Map params, HttpServletRequest request, HttpServletResponse response) {
        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class);
        log.info("[Controller入参]：" + params);
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 短信提醒
            smsService.doSend("13030891963",
                    "用户[" + (String) request.getAttribute("ygxm") + "]"
                            + "在" + sdf.format(new Date())
                            + "下载了YM报表：" + params.toString()
            );
            //
            Map temp = statisticService.doGetYM(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            List<Yjyy_PdjhDTO> res = (List<Yjyy_PdjhDTO>) temp.get("data");
            if (!CollectionUtils.isEmpty(res)) {
                //excel列头信息
                String[] heads = {"姓名", "性别", "年龄", "身份证号", "家庭地址", "取号时间", "叫号人员", "叫号窗口", "备注"};
                List<String[]> dataList = new ArrayList<String[]>();
                String[] objs = null;
                for (int i = 0; i < res.size(); i++) {
                    Yjyy_PdjhDTO user = res.get(i);
                    objs = new String[heads.length];
                    objs[0] = String.valueOf(user.getBrxm() == null ? "" : user.getBrxm());
                    objs[1] = String.valueOf(user.getBrxb() == null ? "" : user.getBrxb());
                    objs[2] = String.valueOf(user.getBrnl() == null ? "" : user.getBrnl());
                    objs[3] = String.valueOf(user.getSfzh() == null ? "" : user.getSfzh());
                    objs[4] = String.valueOf(user.getJtdz() == null ? "" : user.getJtdz());
                    objs[5] = sdf.format(user.getYysj());
                    objs[6] = String.valueOf(user.getJhryxm() == null ? "" : user.getJhryxm());
                    objs[7] = String.valueOf(user.getJhzs() == null ? "" : user.getJhzs());
                    objs[8] = String.valueOf(user.getBzxx() == null ? "" : user.getBzxx());
                    dataList.add(objs);
                }
                ExcelData excelData = new ExcelData();
                excelData.setFileName(UUID.randomUUID().toString() + ".xls");
                excelData.setHead(heads);
                excelData.setData(dataList);
                ExcelUtil.exportExcel(response, excelData);
                return "success";
            }
        } catch (Exception ex) {
            log.error("[不期望的异常]", ex);
        }
        return "fail";
    }

    /**
     * 导出excel（来院登记）
     *
     * @return
     */
    @RequestMapping(value = "/exportExcle_Lydj")
    public String exportExcle_Lydj(@RequestBody Map params, HttpServletRequest request, HttpServletResponse response) {
        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class);
        log.info("[Controller入参]：" + params);
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 短信提醒
            smsService.doSend("13030891963",
                    "用户[" + (String) request.getAttribute("ygxm") + "]"
                            + "在" + sdf.format(new Date())
                            + "下载了LYDJ报表：" + params.toString()
            );
            //
            Map temp = statisticService.doGetLydj(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            List<T_LydjExtDTO> res = (List<T_LydjExtDTO>) temp.get("data");
            if (!CollectionUtils.isEmpty(res)) {
                //excel列头信息
                String[] heads = {"姓名", "性别", "年龄", "身份证号", "卡号", "联系电话", "家庭地址", "来院目的", "登记人员", "登记时间", "院区", "近期发热史", "近期中高风险区旅居史", "近期中高风险区接触史", "备注"};
                List<String[]> dataList = new ArrayList<String[]>();
                String[] objs = null;
                for (int i = 0; i < res.size(); i++) {
                    T_LydjExtDTO user = res.get(i);
                    objs = new String[heads.length];
                    objs[0] = String.valueOf(user.getBrxm());
                    objs[1] = String.valueOf(user.getBrxb() == null ? "" : user.getBrxb());
                    objs[2] = String.valueOf(user.getBrnl() == null ? "" : user.getBrnl());
                    objs[3] = String.valueOf(user.getSfzh() == null ? "" : user.getSfzh());
                    objs[4] = String.valueOf(user.getJzkh() == null ? "" : user.getJzkh());
                    objs[5] = String.valueOf(user.getLxdh() == null ? "" : user.getLxdh());
                    objs[6] = String.valueOf(user.getJtdz() == null ? "" : user.getJtdz());
                    objs[7] = String.valueOf(user.getLymd() == null ? "" : user.getLymd());
                    objs[8] = String.valueOf(user.getDjryxm());
                    objs[9] = sdf.format(user.getDjsj());
                    objs[10] = String.valueOf(user.getYqbszw());
                    objs[11] = String.valueOf(user.getFrs() == null ? "" : user.getFrs());
                    objs[12] = String.valueOf(user.getLjs() == null ? "" : user.getLjs());
                    objs[13] = String.valueOf(user.getJcs() == null ? "" : user.getJcs());
                    objs[14] = String.valueOf(user.getBzxx() == null ? "" : user.getBzxx());
                    dataList.add(objs);
                }
                ExcelData excelData = new ExcelData();
                excelData.setFileName(UUID.randomUUID().toString() + ".xls");
                excelData.setHead(heads);
                excelData.setData(dataList);
                ExcelUtil.exportExcel(response, excelData);
                return "success";
            }
        } catch (Exception ex) {
            log.error("[不期望的异常]", ex);
        }
        return "fail";
    }


    /**
     * 获取'疫苗叫号'报表
     *
     * @param params
     * @param request
     * @return
     */
    @RequestMapping("getYM")
    public String getYM(@RequestBody Map params, HttpServletRequest request) {
        ReplyMsgDTO replyMsgDTO = new ReplyMsgDTO();

        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class);
        log.info("[Controller入参]：" + params);

        try {
            Map temp = statisticService.doGetYM(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            replyMsgDTO.setStatus(true);
            replyMsgDTO.setDetail(new Gson().toJson(temp));
        } catch (Exception ex) {
            // 业务失败
            replyMsgDTO.setStatus(false);
            replyMsgDTO.setDetail(ex.getMessage());
            // 异常日志
            if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
            else log.error("[不期望的异常]", ex);
        }

        //
        String replyMsgStr = new Gson().toJson(replyMsgDTO);
        if (replyMsgDTO.isStatus() == true) {
            log.info("[Controller出参]：报表内容（略）");
        } else {
            log.info("[Controller出参]：" + replyMsgStr);
        }

        return replyMsgStr;
    }


    /**
     * 获取'来院登记'报表
     *
     * @param params
     * @param request
     * @return
     */
    @RequestMapping("getLydj")
    public String getLydj(@RequestBody Map params, HttpServletRequest request) {
        ReplyMsgDTO replyMsgDTO = new ReplyMsgDTO();

        // 日志
        Logger log = LoggerFactory.getLogger(StatisticController.class);
        log.info("[Controller入参]：" + params);

        try {
            Map temp = statisticService.doGetLydj(params); /* 进入Service层处理业务，根据是否发生异常判断业务是否成功 */
            replyMsgDTO.setStatus(true);
            replyMsgDTO.setDetail(new Gson().toJson(temp));
        } catch (Exception ex) {
            // 业务失败
            replyMsgDTO.setStatus(false);
            replyMsgDTO.setDetail(ex.getMessage());
            // 异常日志
            if (ex instanceof ChyException) log.error("[错误]" + ex.getMessage());
            else log.error("[不期望的异常]", ex);
        }

        //
        String replyMsgStr = new Gson().toJson(replyMsgDTO);
        if (replyMsgDTO.isStatus() == true) {
            log.info("[Controller出参]：报表内容（略）");
        } else {
            log.info("[Controller出参]：" + replyMsgStr);
        }

        return replyMsgStr;
    }
}


class Student {
    String name;
    int age;
}
